package com.nowcoder.community.c_service;

import com.nowcoder.community.a_entity.DiscussPost;
import com.nowcoder.community.b_dao.elasticsearch.DiscussPostRepository;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>——————————————————————————————————————————————-————
 * <p> ElasticsearchService：ES单独写个Service
 * <p>——————————————————————————————————————————————-————
 */
@Service
public class ElasticsearchService {
    @Autowired
    private DiscussPostRepository discussRepository;
    @Autowired
    private ElasticsearchTemplate elasticTemplate;


    //插入1条(因为网页访问就是1条1条插出来的)
    public void saveDiscussPostInES(DiscussPost post){
        discussRepository.save(post);
    }
    //删除1条
    public void deleteDiscussPostInEsByid(int id){
        discussRepository.deleteById(id);//这是我写的空接口（spring自己补充的方法）
    }



    //复杂的是搜索（直接粘Test，去掉sout，之后引入3个参数改内部代码+f返回参数）
    public Page<DiscussPost> searchDiscussPostInES(String keyword, int current, int limit) {
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content"))

                .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
                .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
                .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))

                .withPageable(PageRequest.of(current, limit))

                .withHighlightFields(//里面是逗号,参数  可不是;;
                        new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
                        new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")
                ).build();


        //下面Templates底层处理高亮标签em加入
        //先取出来for:里面挨个处理高亮
        /**
         * <p>——————————————————————————————————————————————-————
         * <p> 这里return 大改！：
         * <p>——————————————————————————————————————————————-————
         */
        return elasticTemplate.queryForPage(searchQuery,
                DiscussPost.class,
                new SearchResultMapper() {
                    @Override
                    public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {
                        //这里面后期就是粘？
                        SearchHits hits = response.getHits();//是传入参数SearchResponse，老师简短化名字了
                        if (hits.getTotalHits() <= 0) return null;//特


                        List<DiscussPost> list = new ArrayList<>();//结果这个格式生背
                        //正式取出处理
                        for (SearchHit hit : hits) {
                            DiscussPost post = new DiscussPost();

                            String id = hit.getSourceAsMap().get("id").toString();//json在java取出来是map。。
                            post.setId(Integer.valueOf(id));

                            //先都取出来
                            String userId = hit.getSourceAsMap().get("userId").toString();
                            post.setUserId(Integer.valueOf(userId));
                            String title = hit.getSourceAsMap().get("title").toString();
                            post.setTitle(title);
                            String content = hit.getSourceAsMap().get("content").toString();
                            post.setContent(content);
                            String status = hit.getSourceAsMap().get("status").toString();
                            post.setStatus(Integer.valueOf(status));
                            String createTime = hit.getSourceAsMap().get("createTime").toString();
                            post.setCreateTime(new Date(Long.valueOf(createTime)));
                            String commentCount = hit.getSourceAsMap().get("commentCount").toString();
                            post.setCommentCount(Integer.valueOf(commentCount));


                            //再拿出title和content加高亮(高亮在查询对象初始化的时候写好的 上面)

                            HighlightField titleField = hit.getHighlightFields().get("title");
                            if (titleField != null) post.setTitle(titleField.getFragments()[0].toString());

                            HighlightField contentField = hit.getHighlightFields().get("content");
                            if (contentField != null) post.setContent(contentField.getFragments()[0].toString());

                            //最后加入到list中（每个map）【自猜：类似L《M《S，O》》？】
                            list.add(post);
                        }


                        //return除了第一个是list自己造的，其他生抄死的
                        return new AggregatedPageImpl(list,
                                pageable,
                                hits.getTotalHits(),
                                response.getAggregations(),
                                response.getScrollId(),
                                hits.getMaxScore());
                    }
                });

    }

}
